package service

import (
	"GopherFocus/app/model"
	"GopherFocus/app/shared"
	"GopherFocus/library/response"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
)

var Middleware = middlewareService{
	loginUrl: "/login",
}

type middlewareService struct {
	loginUrl string
}

// 获取用户登录URL
func (s *middlewareService) GetLoginUrl() string {
	return s.loginUrl
}

// 将自定义上下文绑定到请求上下文中
func (s *middlewareService) Ctx(r *ghttp.Request) {
	// 初始化自定义上下文
	customCtx := &model.Context{
		Session: r.Session,
		Data:    make(g.Map),
	}
	// 将自定义上下文绑定到请求上下文中
	shared.Context.Init(r, customCtx)
	// 获取管理员ID
	adminId := g.Cfg().GetUint("setting.adminId", model.DefaultAdminId)
	// 如果用户已登录，则将用户信息存入上下文中
	if userEntity := Session.GetUser(r.Context()); userEntity != nil {
		customCtx.User = &model.ContextUser{
			Id:       userEntity.Id,
			Passport: userEntity.Passport,
			Password: userEntity.Password,
			Nickname: userEntity.Nickname,
			Avatar:   userEntity.Avatar,
			IsAdmin:  userEntity.Id == adminId,
		}
	}
	// 绑定模板变量到当前请求
	// 将自定义的上下文对象传递到模板变量中使用
	r.Assigns(g.Map{
		"Context": customCtx,
	})
	// 执行下一步请求逻辑
	r.Middleware.Next()
}

// 前台系统权限控制，用户必须登陆才能访问
// 1.先看懂
// 2.以input和output为主线来看整个流程
// 3.下手敲代码
func (s *middlewareService) Auth(r *ghttp.Request) {
	// 1.获取当前用户信息，如果Session中已存在该用户信息，则直接跳过权限验证
	user := Session.GetUser(r.Context())
	if user == nil {
		// 2.用户未登录或Session信息已过期，返回提示信息
		// 为什么这里不处理error
		Session.SetNotice(r.Context(), &model.SessionNotice{
			Type:    model.SessionNoticeTypeWarn,
			Content: "未登录或会话已过期，请登录后继续",
		})
		// 3.如果是Get请求，记录当前URL，等登录之后重新调整到当前URL
		// r.GetUrl()获取当前请求URL
		if r.Method == "GET" {
			Session.SetLoginReferer(r.Context(), r.GetUrl())
		}
		// 4.跳转到登录页面，重新登录
		if r.IsAjaxRequest() {
			// 由于传入的r是当前Auth中的r，所以在JsonExit中调用r.Exit()会退出Auth函数
			response.JsonExit(r, 1, "", s.loginUrl)
		} else {
			// 跳转到指定URL
			r.Response.RedirectTo(s.loginUrl)
		}
	}
	r.Middleware.Next()
}
